﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Threading;

namespace Nero_demo
{
    class MouseHelper
    {
        #region 控制鼠标移动

        //移动鼠标 
        public const int MOUSEEVENTF_MOVE = 0x0001;
        //模拟鼠标左键按下 
        public const int MOUSEEVENTF_LEFTDOWN = 0x0002;
        //模拟鼠标左键抬起 
        public const int MOUSEEVENTF_LEFTUP = 0x0004;
        //模拟鼠标右键按下 
        public const int MOUSEEVENTF_RIGHTDOWN = 0x0008;
        //模拟鼠标右键抬起 
        public const int MOUSEEVENTF_RIGHTUP = 0x0010;
        //模拟鼠标中键按下 
        public const int MOUSEEVENTF_MIDDLEDOWN = 0x0020;
        //模拟鼠标中键抬起 
        public const int MOUSEEVENTF_MIDDLEUP = 0x0040;
        //标示是否采用绝对坐标 
        public const int MOUSEEVENTF_ABSOLUTE = 0x8000;

        [Flags]
        public enum MouseEventFlag : int
        {
            Move = 0x0001,
            LeftDown = 0x0002,
            LeftUp = 0x0004,
            RightDown = 0x0008,
            RightUp = 0x0010,
            MiddleDown = 0x0020,
            MiddleUp = 0x0040,
            XDown = 0x0080,
            XUp = 0x0100,
            Wheel = 0x0800,
            VirtualDesk = 0x4000,
            Absolute = 0x8000
        }

        //[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool SetCursorPos(int X, int Y);
        [DllImport("user32.dll")]
        public static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

        #endregion

        #region 获取坐标钩子

        [StructLayout(LayoutKind.Sequential)]
        public class POINT
        {
            public int X;
            public int Y;
        }

        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public POINT pt;
            public int hwnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }

        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        //安装钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        //卸载钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        //调用下一个钩子
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);


        /// <summary>   
        /// 获取鼠标的坐标   
        /// </summary>   
        /// <param name="lpPoint">传址参数，坐标point类型</param>   
        /// <returns>获取成功返回真</returns>   
        [DllImport("User32")]
        public extern static bool GetCursorPos(ref Point lpPoint);


        [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern long GetLastError();
        #endregion

        #region sendInput 模拟键鼠输入
        [DllImport("user32.dll")]
        private static extern UInt32 SendInput(UInt32 nInputs, Input[] pInputs, int cbSize);

        [StructLayout(LayoutKind.Explicit)]
        private struct Input
        {
            [FieldOffset(0)] public Int32 type;
            [FieldOffset(4)] public MouseInput mi;
            [FieldOffset(4)] public tagKEYBDINPUT ki;
            [FieldOffset(4)] public tagHARDWAREINPUT hi;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MouseInput
        {
            public Int32 dx;
            public Int32 dy;
            public Int32 Mousedata;
            public Int32 dwFlag;
            public Int32 time;
            public IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct tagKEYBDINPUT
        {
            Int16 wVk;
            Int16 wScan;
            Int32 dwFlags;
            Int32 time;
            IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct tagHARDWAREINPUT
        {
            Int32 uMsg;
            Int16 wParamL;
            Int16 wParamH;
        }

        const int MouseEvent_Absolute = 0x8000;
        const int MouserEvent_Hwheel = 0x01000;
        const int MouseEvent_Move = 0x0001;
        const int MouseEvent_Move_noCoalesce = 0x2000;
        const int MouseEvent_LeftDown = 0x0002;
        const int MouseEvent_LeftUp = 0x0004;
        const int MouseEvent_MiddleDown = 0x0020;
        const int MouseEvent_MiddleUp = 0x0040;
        const int MouseEvent_RightDown = 0x0008;
        const int MouseEvent_RightUp = 0x0010;
        const int MouseEvent_Wheel = 0x0800;
        const int MousseEvent_XUp = 0x0100;
        const int MousseEvent_XDown = 0x0080;
        #endregion

        public void MouseClick(Point point)
        {
            int left = point.X;
            int top = point.Y;

            MouseInput myMinput = new MouseInput();
            myMinput.dx = left * (65535 / screenWidth);
            myMinput.dy = top * (65535 / screenHeight);
            myMinput.Mousedata = 0;
            myMinput.dwFlag = MouseEvent_Absolute | MouseEvent_Move | MouseEvent_LeftDown | MouseEvent_LeftUp;

            myMinput.time = 0;
            Input[] myInput = new Input[1];
            myInput[0] = new Input();
            myInput[0].type = 0;
            myInput[0].mi = myMinput;

            UInt32 result = SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));
        }

        public void MouseWheel(int delta)
        {
            MouseInput myMinput = new MouseInput();
            myMinput.Mousedata = delta;
            myMinput.dwFlag = MouseEvent_Wheel;

            myMinput.time = 0;
            Input[] myInput = new Input[1];
            myInput[0] = new Input();
            myInput[0].type = 0;
            myInput[0].mi = myMinput;

            UInt32 result = SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));
        }

        public void MouseDragX(int startx, int endx, int y)
        {
            int left = startx;
            int top = y;

            MouseInput myMinput;
            Input[] myInput;

            int deltaY = 2;

            for (int delta = 0; delta < endx - startx; delta++)
            {
                myMinput = new MouseInput();
                myMinput.dx = (left + delta) * (65535 / screenWidth);
                myMinput.dy = (top + deltaY) * (65535 / screenHeight);
                myMinput.Mousedata = 0;
                myMinput.dwFlag = MouseEvent_Absolute | MouseEvent_Move | MouseEvent_LeftDown;

                myMinput.time = 0;
                myInput = new Input[1];
                myInput[0] = new Input();
                myInput[0].type = 0;
                myInput[0].mi = myMinput;

                UInt32 result = SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));
                Thread.Sleep(1);
                deltaY = -deltaY;
            }

            myMinput = new MouseInput();
            myMinput.Mousedata = 0;
            myMinput.dwFlag = MouseEvent_LeftUp;

            myMinput.time = 0;
            myInput = new Input[1];
            myInput[0] = new Input();
            myInput[0].type = 0;
            myInput[0].mi = myMinput;

            SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));
        }

        public void MouseDoubleClick(Point point)
        {
            int left = point.X;
            int top = point.Y;

            MouseInput myMinput = new MouseInput();
            myMinput.dx = left * (65535 / screenWidth);
            myMinput.dy = top * (65535 / screenHeight);
            myMinput.Mousedata = 0;
            myMinput.dwFlag = MouseEvent_Absolute | MouseEvent_Move | MouseEvent_LeftDown | MouseEvent_LeftUp;

            myMinput.time = 0;
            Input[] myInput = new Input[1];
            myInput[0] = new Input();
            myInput[0].type = 0;
            myInput[0].mi = myMinput;

            SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));

            myMinput = new MouseInput();
            myMinput.Mousedata = 0;
            myMinput.dwFlag = MouseEvent_LeftDown | MouseEvent_LeftUp;

            myMinput.time = 0;
            myInput = new Input[1];
            myInput[0] = new Input();
            myInput[0].type = 0;
            myInput[0].mi = myMinput;

            SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));
        }

        public MouseHelper()
        {
            Screen screen = Screen.PrimaryScreen;
            Rectangle bounds = screen.Bounds;
            screenWidth = bounds.Width;
            screenHeight = bounds.Height;
        }


        private int screenWidth;
        private int screenHeight;
    }
}
